#include <Core/Box/BoxInstance.h>

#include <boost/assert.hpp>

#define MAKE_DEBUG_MESSAGE(m) (std::string(__FUNCTION__) + std::string(m))

namespace BoxCore {

namespace ErrorStrings {

std::string const INSTANCE_INITIALIZED = "The Box instance already initialized";
std::string const INSTANCE_INITIALIZED_BAD = "The Box instance not initialized or initialized with not valid ifaces";

} // namespace ErrorStrings

BoxInstance::BoxInstance(BoxInstanceParams const & params) 
	: m_params(params), m_lock(), m_boxEvSubscribers(), m_transport(), m_commandIface()
{
}
 
BoxInstance::~BoxInstance() 
{
	interruptInstance();
}
	
bool BoxInstance::initialize(ITransportLayerPtr transport, IBoxCommandIFacePtr commandIface) 
{	
	BOOST_ASSERT(transport != NULL || commandIface != NULL);
	boost::lock_guard<boost::mutex> guard(m_lock);
	if (m_transport || m_commandIface) 
		return setLastError(ErrorStrings::INSTANCE_INITIALIZED);	
	m_transport = transport; 
	m_commandIface = commandIface;
	return true;
}

bool BoxInstance::registrEventSubscriber(IBoxEventSubscriberPtr boxEvSubscriber) 
{
	BOOST_ASSERT(boxEvSubscriber != NULL);
	boost::lock_guard<boost::mutex> guard(m_lock);
	if (boxEvSubscriber) {
		m_boxEvSubscribers.push_back(boxEvSubscriber);
		boxEvSubscriber->registred();
		return true;
	}
	return false;
}

void BoxInstance::unregistrEventSubscriber(IBoxEventSubscriberPtr boxEvSubscriber) 
{
	boost::lock_guard<boost::mutex> guard(m_lock);
	// TODO impl this
}
	

bool BoxInstance::startInstance() 
{
	boost::lock_guard<boost::mutex> guard(m_lock);
	if (!m_transport || !m_commandIface)
		return setLastError(ErrorStrings::INSTANCE_INITIALIZED_BAD);
	
	try 
	{
		m_commandIface->initialize();
		m_transport->performAsync(m_commandIface);
	}
	catch (std::exception const & expt)
	{
		return setLastError(expt.what());
	}

	return true;
}

void BoxInstance::interruptInstance() 
{
	try 
	{
		if (m_transport)
			m_transport->interrupt(m_params.closeGraceful);
		if (m_commandIface)
			m_commandIface->interrupt(m_params.closeGraceful);
	}
	catch (std::exception const & expt) 
	{
	}
}

void BoxInstance::waitInstance() 
{
	if (m_transport) m_transport->wait();
}

}

#undef MAKE_DEBUG_MESSAGE

